package com.miyake.dsp.osa.lab.wrapper;

import com.miyake.dsp.ComplexArray;
import com.miyake.dsp.common.CommonTool;
import com.miyake.dsp.filter.FilterImplScilabProxy;
import com.miyake.dsp.filter.FilterSetting;
import com.miyake.dsp.filter.FilterSetting.FilterAlgo;
import com.miyake.dsp.filter.FilterSetting.FilterType;
import com.miyake.dsp.osa.lab.Calculator;
import com.miyake.dsp.osa.lab.LabUiAnnotation;
import com.miyake.dsp.otdr.OtdrRxSetting;
@LabUiAnnotation(caption="Otdr Simulator Rx")
public class OtdrSimulatorRxWrapper extends Calculator {
	public static final String INPUT_FREQUENCY = "Sampling Frequency";
	public static final String INPUT_LOSS = "In Loss";
	public static final String INPUT_ATT = "Attenuator";
	public static final String INPUT_BANDWIDTH = "Bandwidth";
	public static final String INPUT_AVERAGE = "Average";
	public static final String OUTPUT = "Out Loss";
	private OtdrRxSetting setting;
	
	public OtdrSimulatorRxWrapper(OtdrRxSetting setting) {
		initInput(INPUT_FREQUENCY);
		initInput(INPUT_LOSS);
		initInput(INPUT_ATT);
		initInput(INPUT_BANDWIDTH);
		initInput(INPUT_AVERAGE);
		initOutput(OUTPUT);
		this.setting = setting; 
	}
	
	@Override
	public synchronized void process() {
		double[] in = this.getInput(INPUT_LOSS).getRealPart();
		double ceiling = setting.getCeiling();
		double noiseLevel = setting.getNoise();
		double average;
		if (getInput(INPUT_AVERAGE) != null) {
			average = getInput(INPUT_AVERAGE).getRealPart()[0];
		}
		else {
			average = setting.getAverageCount();
		}
		
		double[] noise = CommonTool.getWhiteNoise(in.length, noiseLevel/Math.sqrt(average), 0);
		double samplingFrequency;
		double bandwidth;
		
		if (getInput(INPUT_FREQUENCY) != null) {
			samplingFrequency = getInput(INPUT_FREQUENCY).getRealPart()[0];
		}
		else {
			samplingFrequency = setting.getSamplingFrequency();
		}
		if (getInput(INPUT_BANDWIDTH) != null) {
			bandwidth = getInput(INPUT_BANDWIDTH).getRealPart()[0];
		}
		else {
			bandwidth = setting.getBandwidth();
		}

		FilterSetting filterSetting = new FilterSetting();
		FilterImplScilabProxy filter = new FilterImplScilabProxy(filterSetting);
		filterSetting.setFilterAlgo(FilterAlgo.Butterworth);
		filterSetting.setFilterType(FilterType.Lowpass);
		filterSetting.setOrder(1);
		filterSetting.setFrequency(samplingFrequency);
		
		double att;
		if (getInput(INPUT_ATT) != null) {
			att = getInput(INPUT_ATT).getRealPart()[0];
		}
		else {
			att = setting.getAttenuation();
		}
		double[] out = CommonTool.getGained(in, att * -1.0);
		out = CommonTool.getMixed(out, noise);
		out = CommonTool.getSmoothed(out, setting.getMovingAverage());
		filterSetting.setCutoff1(bandwidth);
		filter.setSource(new ComplexArray(out));
		out = filter.getProcessed().getRealPart();
		out = CommonTool.getLimited(out, ceiling);
		this.setOutput(OUTPUT, out);

	}

	@Override
	public Object getSetting() {
		return setting;
	}

}
